package web

import (
	"sync"

	"commonUtils/utils"
)

// Channel Channel
type Channel struct {
	WsConfig
	Name                string
	broadcast           chan []byte
	close               chan bool
	clients             map[*Conn]bool
	muClients           sync.RWMutex
	serverDeleteChannel func(string)
}

// Has 判断频道中是否包含该连接
func (c *Channel) Has(conn *Conn) bool {
	c.muClients.RLock()
	defer c.muClients.RUnlock()
	for c := range c.clients {
		if c == conn {
			return true
		}
	}
	return false
}

// Add 添加连接
func (c *Channel) Add(conn *Conn) {
	c.muClients.Lock()
	defer func() {
		c.muClients.Unlock()
		if c.OnConnected != nil {
			c.OnConnConnected(c, conn)
		}
	}()
	c.clients[conn] = true
}

// Delete 删除连接
func (c *Channel) Delete(conn *Conn) {
	c.muClients.Lock()
	var isHas = false
	defer func() {
		c.muClients.Unlock()
		if isHas && c.OnConnDisconnected != nil {
			c.OnConnDisconnected(c, conn)
		}
	}()
	if _, ok := c.clients[conn]; ok {
		delete(c.clients, conn)
		isHas = true
		if len(c.clients) == 0 && c.serverDeleteChannel != nil {
			go c.serverDeleteChannel(c.Name)
		}
	}
}

// Count 获取频道连接数
func (c *Channel) Count() int {
	c.muClients.RLock()
	defer c.muClients.RUnlock()
	return len(c.clients)
}

// Process 频道消息过程
func (c *Channel) Process() {
	defer func() {
		close(c.close)
		close(c.broadcast)
		utils.Info("channel %s process exit", c.Name)
	}()
	for {
		select {
		case _ = <-c.close:
			return
		case message := <-c.broadcast:
			c.muClients.RLock()
			if len(c.clients) > 0 {
				for client := range c.clients {
					go client.Send(message)
				}
			} else if nil != c.serverDeleteChannel {
				go c.serverDeleteChannel(c.Name)
			}
			c.muClients.RUnlock()
		}
	}

}

// Exit 退出
func (c *Channel) Exit() {
	c.close <- true
}

// Broadcast 广播
func (c *Channel) Broadcast(d []byte) {
	c.broadcast <- d
}
